1986-Club80 Nr.17 S.8-15

Wie Phönix aus der Asche

Vier Computer in einem Schrotthaufen

Gerald Schröder

Die Beilage von Arnulf und Helmut im letzten Info hat Euch sicherlich geschockt, denn schließlich verfügt nicht jedermann über einen IIIs, den er aufmotzen kann. Mir fehlt zwar das Kleingeld für einen IIIs, aber deshalb gönne ich den IIIs-Besitzern diesen Triumpf noch lange nicht. Deshalb habe ich kurzerhand Arnulfs Idee abgekupfert und auf den schon in der Überschrift erwähnten TRS80 angewandt. Wer sich jetzt extra einen IIIs gekauft hat, um mit Arnulf gleich ziehen zu können, ist selbst schuld.

Wie sieht das in der Praxis aus? Ganz einfach, Ihr belagert einfach den schon mehrmals erwähnten Helmut, bis er Euch einen Banker einbaut. Dann tippt Ihr das folgende Programm ab oder laßt es Euch vom nächsten Diskothekar schicken. Wenn Ihr dann <Shift><Down-Arrow><Ziffer> betätigt, wobei Ziffer := 0 bis 3, könnt Ihr zwischen 4 Computern hin- und herschalten. In jedem Computer kann ein Programm laufen, solange dieses Programm

  1. die Interrupts abgeschaltet läßt
  2. keine fiesen Nebeneinbauten benutzt.

Punkt 2 bezieht sich auf Graphikkarten o.ä. Damit wir uns richtig verstehen: benutzen darf das Progamm sie schon, solange beim Sprung zu einem anderen Computer die Sache wieder ausgeschaltet ist. Der weiß nämlich überhaupt nichts davon.

Gerettet wird der Speicher ab 3000h aufwärts. Darunter sollte ein festes ROM sein, das gefälligst nicht geändert wird.

Einige interne Notierungen:
  • die Umschaltung ist in die normale Interrupt-Routine des Gdos/Newdos-SYS0 eingebaut.
  • alle Routinen liegen in Bank 1
  • die Banks 1, 2 und 3 enthalten die "unteren" Hälften der Computer 1-3, jeweils von B000-FFFF
  • die Banks 0 und 4-6 enthalten die "oberen" Hälften der Computer 0-3
  • die "untere" Hälfte von Computer 0 wird jeweils mit der des momentan aktiven Computers getauscht.
  • es werden jeweils nur die "unteren" Hälften vertauscht (weil das Common nun mal eine untere Bank ist). während die "oberen" Hälften nur umgeschaltet werden müssen
  • d.h.: wenn der Computer 1 auf 3 umgeschaltet wird, wird zuerst Computer 0 selektiert, bevor Computer 3 endgültig ans Rohr kommt
  • deshalb spielt sich auf dem Bildschirm bei einer solchen Umschaltung kurz ein Wirrwarr ab, das aber nur mühsam zu umgehen wäre
  • das Vertauschen läft folgendermaßen ab:
       (von Bank 1 aus) 7E00-7FFF nach Bank 1 retten
          Tausch-Routinen nach 7E00 (ins Common) übertragen
          Tausch-Routinen starten
             gerettetes 7E00 ff. mit dem aus sel. Bank tauschen
             Common 3000-7DFF mit sel. Bank tauschen
             (dabei Buffer 7E00-7FFF benutzt)
             zurück nach Bank 1
          geretteten Bereich 7E00 ff. ins Common
          stareten des Computers
  • um unerwünschte Nebeneffekte (wie Druckerausgabe) auszuschließen, wird der I/O-Bereich 3700-37FF nicht gerettet
  • das Programm ist lange nicht so elegant wie Arnulfs Lösung, aber es tut seinen Dienst.
So, das war's schon, besorgt Euch 256kB und los geht's mit SIDEKICK

Gerald Schröder

Hardware: Helmut
Literatur: Arnulfs Listing


00001;		SIDEKICK für TRS80-Kompatible mit Helmuts Banker
00002;		im Dez. 1986 von Gerald Schröder
00003;		nach einer Idee von Arnulf Sopp
00004
00005
00006		ORG	3300h		;Stack ab hier abwärts!
00007
00008 start	LD	(spbuf),SP	;SP retten
00009
00010		LD	HL,retpro	;Rückkehr-Adresse (bei 1.
00011		USH	HL		;Aufruf Comp. 1-3)
00012		LD	B,4		;Stack vorbereiten
00013 loop1	PUSH	AF
00014		DJNZ	loop1
00015		LD	(rettsp),SP	;retten für Comp. 1-3
00016
00017		LD	A,1		;Bank
00018		DI
00019		OUT	(0ech),A	;einschalten
00020		LD	HL,schalt	;Umschalt-Routine
00021		LD	DE,schalt-diff	;in Bank 1
00022		LD	BC,ende-schalt
00023		LDIR
00024		XOR	A
00025		OUT	(0ehc),A	;wieder Bank 0
00026
00027		LD	HL,umleit	;Umleitung in Interrupt-
00028		LD	DE,umleit-diff1	;Routine anlegen
00029		LD	BC,ende1-umleit
00030		LDIR
00031
00032		LD	HL,zurück	;Rücksprung
00033		LD	DE,zurück-diff2	;in SYS0 anlegen
00034		LD	BC,ende2-zurück
00034		LDIR
00036
00037		LD	SP,start	;SP neu setzen
00038
00039		LD	B,3		;drei Computer
00040 loop2	CALL	copy		;in die Banks
00041		DJNZ	loop2
00042
00043		EI
00044		LD	SP,0000		;SP zurück
00045 sobuf	EQU	$-2
00046
00047 retpro	RET			;ab
00048
00049
00050;		kopiert oberen und unteren Teil in Banks
00051
00052		PUSH	BC		;Zähler retten
00053		LD	A,B		;als Bank-Nr.
00054		OUT	(0ech),A	;für unteren Teil
00055		LD	DE,8000h+3000h	;Ziel = 0b000h
00056		LD	D,50h		;Länge = 5000h
00057		LD	C,E
00058		LD	H,30h		;Anfang 3000h
00059		LD	L,E
00060		LDIR			;(3000-7fff)=>(b000-ffff)
00061
00062		ADD	A,3		;für oberen Teil
00063		EX	AF,AF'		;retten
00064		LD	D,60h		;Buffer: 6000h-6100h
00065
00066 loop3	INC	B		;ein Sektor
00067		XOR	A		;Bank 0
00068		OUT	(0ech,A		;ein
00069		LDIR			;Sektor aus 0 in Buffer
00070		DEC	D		;Sektor-Zeiger auf 6000h
00071		LD	A,H		;Quelle- als Zielzeiger
00072		LD	H,D
00073		LD	D,A
00074		DEC	D
00075		INC	B
00076		EX	AF,AF'		;Bank-Nr. zurück
00077		OUT	(0ech),A	;anwählen
00078		EX	AF,AF'		;wieder rettten
00079		LDIR			;Aus Buffer in Bank
00080		DEC	H		;Buffer auf 6000h
00081		LD	A,D		;und wieder tauschen
00082		LD	D,H
00083		LD	H,A
00084		OR	L		;schon über ffffh hinaus?
00085		JR	NZ,loop3	;nein
00086		OUT	(0ech),A	;ja, Bank 0 ein
00087		POP	BC		;Zähler zurück
00088		RET
00089
00090
00091
00092 ;		Umleitung in der Interrupt-Routine
00093
00094 diff1	EQU	$-45f6h
00095 umleit	LD	A,1		;Bank 1
00096		OUT	(0ech),A	;ein
00097		JP	schalt-diff	;und springen
00098 ende1	EQU	$
00099
00100 ;		Rückkehr-Routine
00101
00102 diff2	EQU	$-4053h
00103
00104 zurück	OUT	(0ech),A	;Bank x für oben an
00105		JP	45fdh		;weiter
00106 ende2	EQU	$
00107
00108
00109
00110 ;		Schaltroutine in Bank 1
00111 ;		Ansprung von Interrupt-Routine aus
00112
00113 diff	EQU	$-3600h
00114 schalt	LD	HL,3880h	;Tast.-Zeile
00115		BIT	0,(HL)		;SHIFT?
00116		JR	Z,goon3		;nein, ab
00117		SRL	L
00118		BIT	4,(HL)		;Down-Arrow?
00119		JR	Z,goon3		;nein, ab
00120		SRL	L
00121		SRL	L		;Tast.-zeile 3810h
00122		LD	A,(HL)
00123		AND	0fh		;Taste 0 bis 32
00124		JR	Z,goon3		;nein, ab
00125		LD	L,A		;retten
00126		XOR	A		;Zähler 0
00127 goon1	INC	A		;+1
00128		SRL	L		;solange
00129		JR	NC,goon1	;bis Taste erreicht
00130		DEC	A		;Zähler korrigieren
00131
00132		LD	(rettsp)	;SP retten
00133
00134		LD	DE,goon4-diff	;Rückkehradresse
00135		JZ	spsuch		;neuen SP berechnen
00136
00137 goon4	PUSH	IX		;Register dieses COMP.
00138		PUSH	IY		;retten
00139		EX	AF,AF'
00140		EXX
00141		PUSH	AF
00142		PUSH	BC
00143		PUSH	DE
00144		PUSH	HL
00145		LD	SP,ende-diff+150 ;zeitweilig neu
00146
00147		EX	AF,AF'		;Comp.-Nr. zurück
00148		CP	0		;schon eingeschaltet?
00149 momba	EQU	$-1
00150		JR	Z,abgang	;ja
00151		LD	(banku-diff),A	;dort unterer Teil
00152		OR	A		;Comp. 0?
00153		JR	Z,goon2		;ja, oben = Bank 0
00154		ADD	A,3		;sonst oben = u +3
00155 goon2	LD	(banko-diff),A	;Bank oberer Teil
00156		LD	A,(momba-diff)	;Comp. 0 eingeschaltet?
00157		OR	A
00158		CALL	NZ,tausch-diff	;nein, Comp. 0 holen
00159		LD	A,0		;Bank unterer Teil
00160 banku	EQU	$-1
00161		LD	(momba-diff),A	;sichern: mom. Comp.
00162		OR	A		;falls nicht 0
00163		CALL	NZ,tausch-diff	;Computer holen
00164
00165 abgang	LD	DE,goon5-diff
00166		JR	spsuch
00167 goon5	LD	B,12		;SP korrigieren
00168 ab1	DEC	SP
00169		DJNZ	ab1
00170 					;Register des
00171		POP	HL		;Computers zurück
00172		POP	DE
00173		POP	BC
00174		POP	AF
00175		EXX
00176		EX	AF,AF'
00177		POP	IY
00178		POP	IX
00179		LD	SP,(rettsp)	;SP restaurieren
00180
00181 goon3	LA	A,(37ech)	;urspr, Int.-rout.
00182		LD	A,(37e0h)
00183		RLCA
00184		LD	A,0		;Bank-Nr. für oberen Teil
00185 banko	EQU	$-1
00186		JP	zurück-diff2	;nach SYS0 für Abgang
00187
00188
00189 ;		Unterprogramm: Stack-Pos. für geg. Comp A
00190 ;		berechnen
00191
00192 spsuch	LD	L,A		;Nr. nach L
00193		LD	H,0
00194		LD	SP,ende.diff+20	;Stack-Offset
00195		LD	B,5		;+32*Comp.-Nr.
00196 sps1	SLA	L
00197		DJNZ	sps1
00198		ADD	HL,SP
00199		LD	SP,HL		;SP in Bank 1 setzen
00200		EX	DE,HL		;Rückspr.adr. nach HL
00201		JP	(HL)		;und ab
00202
00203
00204
00205 ;		Unterprogramm Tausch:
00206 ;		vertauscht unteren Teil von Computer 0 mit dem
00207 ;		eines der drei anderen Computer
00208
00209 tausch	LD	(bankx1-diff),A	;gew. Bank-Nr. sichern
00210		LD	(bankx2-diff),A
00211		LD	(bankx3-diff),A
00212
00213		LD	HL,anf-diff3	;Bereich Tausch-Rout
00214		PUSH	HL		;retten
00215		LD	DE,0a000	;Buffer für Original
00216		LD	BC,0200h
00217		LDIR			;Orig.-Code retten
00218
00219		POP	DE		;7e00h
00220		PUSH	DE
00221		LD	HL,anf-diff	;Routinen zum Tauschen
00222		LD	BC,ende-anf
00223		LDIR			;in die untere Hälfte
00224					;bei 7e00h
00225		LD	(stack-d;if),SP	SP retten
00226		LD	SP,7f00h	;auch nach unten
00227		LD	HL,0fe00h	;7e00h aus Bank x
00228		LD	DE,7f00h	;Buffer
00229		LD	BC,9f00h	;MSB (Buffer in Bank)
00230		CAL	anf-diff3	;Aufruf Tausch-Rout.
00231		LD	SP,0000		;SP zurück
00232 stack	EQU	$-2
00233		POP	DE		;Fe00 zurück
00234		LD	H,9fh		;von 9f00 aus
00235		INC	B		;BC = 0200h
00236		LDIR			;7300-7fff neu füllen
00237		RET
00238
00239
00240 diff3	EQU	$-7e00h
00241 anf	PUSH	BC		;9f00 (x-1) auf Stack
00242		PUSH	DE		;7e00 (z)    "    "
00243		LD	B,1
00244		LD	A,2		;2 Durchläufe
00245
00246 ;7e00-7fff tauschen
00247 loopp	EX	AF,AF'		;Zähler retten
00248		LD	A,0
00249 bankx1	EQU	$-1
00250		OUT	(0ech),A
00251		POP	DE		;retten
00252		POP	AF		;(x-1) zurück
00253		PUSH	HL		;Y retten
00254		PUSH	AF		;(x-1) retten
00255		PUSH	DE		;z retten
00256		LDIR
00257		INC	B
00258		LD	A,1
00259		OUT	(0ech),A
00260		POP	HL		;z zurück
00261		POP	DE		;(x-1) zurück
00262		PUSH	HL		;z retten
00263		LDIR			;y -> z, Bank 1 -> Buffer
00264		INC	B
00265		LD	A,1
00266		OUT	(0ech),A
00267		POP	HL		;z zurück
00268		POP	DE		;(x-1) zurück
00269		LDIR			;y -> z, Bank 1 -> Buffer
00270		INC	B		;(Original-Code)
00271		LD	A,0
00272 bankx2	EQU	$-1
00273		OUT	(0ech),A
00274		POP	HL		;z zurück
00275		POP	AF		;x zurück
00276		POP	DE		;y zurück
00277		PUSH	AF		;x retten
00378		PUSH	HL		;z retten
00279		LDIR			;z -> y, Buffer -> Bankx
00280		INC	B		; (Orig in Bank x)
00281		LD	H,D		;(y+1)
00282		EX	AF,AF'
00283		DEC	A
00284		JR	NZ,loopp
00285
00286 ;Stack: (x+1),z
00287
00288		POP	DE		;Buffer z
00289		POP	AF		;(x+1) weg
00290		LD	H,30h		;Anfang mit unten (3000h)
00291		LD	A,0
00292 bankx3	EQU	$-1
00293		OUT	(0ech),A	;Bank x ein
00294
00295	loop	PUSH	DE		;"Buffer z" retten
00296		PUSH	HL		;"von y" retten
00297		LDIR			;1. Sektor in Buffer
00298
00299		POP	DE		;"nach y" zurück
00300		LD	H,D		;"von z" (aus Bank)
00301		SET	7,H		;deshalb immer >= 8000h
00302		PUSH	HL		;retten
00303		INC	B		;ein Sektor
00304		LDIR			;2. aus Bank nach unten
00305
00306		POP	DE		;"nach x" (Bank)
00307		POP	HL		;"vonZ" (Buffer)
00308		INC	B		;ein Sektor
00309		LDIR			;aus Buffer in Bank
00310
00311		INC	B		;ein Sektor
00312		DEC	H		;Buffer bleibt
00313		LD	A,D		;"von y"
00314		AND	7fh		;immer unter 8000h
00315		LD	D,H		;Buffer in de
00316		LD	H,A		;"von y" in HL
00317		CP	37h		;I/O-Bereich?
00318		JR	NZ,lop		;nein, weiter
00319		INC	H		;ja, überspringen
00320 lop	CP	7eh		;=fertig?
00321		JR	NZ,loop		;weiter wenn <> 7e00
00322
00323		LD	A,1		;Bank1
00324		OUT	(0ech),A	;wieder ein
00325		RET			;fertig
00326 ende	EQU	$-1
00327
00328
00329
00330 rettsp	EQU	4058h
00331
00332
00333		END	start